home *** CD-ROM | disk | FTP | other *** search
- #define LIBQDISPLAY_CORE
- #include "../include/libqdisplay.h"
-
- /*
- * "render" scenes by traversing over the
- * database, marking already-visited things,
- * using the PVS information and the "marksurface"
- * info; use one bsp routine to sort
- */
-
- unsigned char *visibleFaces; //[MAX_MAP_FACES / 8 + 1];
- unsigned char *visibleLeafs; //[MAX_MAP_LEAFS / 8 + 1];
- unsigned char *visibleNodes; //[MAX_MAP_NODES];
-
- int model = 0;
-
- #if 0 // this works if IEEE and, sizeof(float) == sizeof(int)
- #define FLOAT_POSITIVE(x) (*((int *)(&x)) >= 0)
- #else
- #define FLOAT_POSITIVE(x) ((x) >= 0)
- #endif
-
- static int bbox_inside_plane(short *mins, short *maxs, struct dplane_t * pl)
- {
- short pt[3];
-
- // use quick test from graphics gems
- if (FLOAT_POSITIVE(pl->normal[0]))
- pt[0] = maxs[0];
- else
- pt[0] = mins[0];
-
- if (FLOAT_POSITIVE(pl->normal[1]))
- pt[1] = maxs[1];
- else
- pt[1] = mins[1];
-
- if (FLOAT_POSITIVE(pl->normal[2]))
- pt[2] = maxs[2];
- else
- pt[2] = mins[2];
-
- /*
- * each frustum-plane in hesse-form have a positive and a negative half-space
- * we can check if the distance between frustum-plane and point is positive or
- * negative to check where the points is, in the positive or negative
- * half-space
- *
- * if((DotProduct(frustumNormal, point) - frustumDistance) >= 0) -> if(DotProduct(frustumNormal, point) >= frustumDistance)
- * if is visible (lies in positive half-space)
- * else
- * it is invisible (lies in negative half-space)
- */
- return DotProduct(pl->normal, pt) >= pl->dist;
- }
-
- /*
- * is the complete node between the frustum-planes?
- */
- int node_in_frustrum(struct dnode_t * node)
- {
- if (!bbox_inside_plane(node->mins, node->maxs, &planes[0])
- || !bbox_inside_plane(node->mins, node->maxs, &planes[1])
- || !bbox_inside_plane(node->mins, node->maxs, &planes[2])
- || !bbox_inside_plane(node->mins, node->maxs, &planes[3]))
- return 0;
- return 1;
- }
-
- /*
- * is the complete leaf between the frustum-planes?
- */
- int leaf_in_frustrum(struct dleaf_t * node)
- {
- if (!bbox_inside_plane(node->mins, node->maxs, &planes[0])
- || !bbox_inside_plane(node->mins, node->maxs, &planes[1])
- || !bbox_inside_plane(node->mins, node->maxs, &planes[2])
- || !bbox_inside_plane(node->mins, node->maxs, &planes[3]))
- return 0;
- return 1;
- }
-
- /*
- * mark all faces within a given leaf
- */
- void mark_leaf_faces(__memBase, int leaf)
- {
- int contents = bspMem->dleafs[leaf].contents;
- short int i = bspMem->dleafs[leaf].nummarksurfaces;
- unsigned short int *dms = &bspMem->dmarksurfaces[(int)(bspMem->dleafs[leaf].firstmarksurface + i)];
-
- for (--i; i >= 0; i--) {
- int s = *--dms;
- mark_face(s);
- }
- }
-
- /*
- * The visibility lists are used by BSP Leaves, to
- * determine which other leaves are visible from a given BSP Leaf.
- * The Visibility list can be of size 0, in that case it will not be used.
- * The game will crawl if there is no visibility list in a level.
- * u_char vislist[numvislist]; // RLE encoded bit array
- * Basically, the visibility list is an array of bits. There is one such array
- * of bits for each BSP Leaf. They are all stored in the vislist array, and
- * each leaf has an index to the first byte of it's own array
- * The bit number N, if set to 1, tells that when laying in the tree leaf, one
- * can see the leaf number N.
- * The only complication is that this bit array in run-length encoded:
- * when a set of bytes in the array are all zero, they are coded by zero
- * followed by the number of bytes is the set (always more than 1).
- * Normally, the size of the bit array associated to a leaf should be
- * (numleafs+7)/8, but in fact due to the run length encoding, it's usually
- * much less.
- * When the player is in a leaf, the visibility list is used to tag
- * all the leaves that can possibly be visible, and then only those
- * leaves are rendered.
- * Here is an example of decoding of visibility lists:
- * // Suppose Leaf is the leaf the player is in.
- * v = Leaf.vislist;
- * for (L = 1; L < numleaves; v++)
- * {
- * if (visisz[v] == 0) // value 0, leaves invisible
- * {
- * L += 8 * visisz[v + 1] // skip some leaves
- * v++;
- * }
- * else // tag 8 leaves, if needed
- * { // examine bits right to left
- * for (bit = 1; bit != 0; bit = bit * 2, L++)
- * {
- * if (visisz[v] & bit)
- * TagLeafAsVisible(L);
- * }
- * }
- * }
- * Lots of thanks to Tony Myles who fixed the bit mask formula.
- * There is no necessity to unpack the visibility list in memory,
- * because the code to read them is fast enough.
- */
- int visit_visible_leaves(__memBase)
- {
- int n, i;
- unsigned char *vis;
-
- n = find_leaf(bspMem);
-
- if (n == 0 || bspMem->dleafs[n].visofs < 0) {
- memset(visibleLeafs, 0xFF, bspMem->dmodels[model].visleafs * sizeof(unsigned char));
- return 0;
- }
- else {
- memset(visibleLeafs, 0x00, bspMem->dmodels[model].visleafs * sizeof(unsigned char));
- }
-
- vis = bspMem->dvisdata + bspMem->dleafs[n].visofs;
- for (i = 1; i < bspMem->dmodels[model].visleafs;) {
- unsigned char v = *vis++;
-
- if (v == 0) {
- i += *vis++ << 3; // * 8
- }
- else {
- if (v & 1)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 2)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 4)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 8)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 16)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 32)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 64)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- if (v & 128)
- visibleLeafs[i >> 3] |= (1 << (i & 7));
- i++;
- }
- }
- return 1;
- }
-
- // during a bsp recursion, draw all of the faces
- // stored on this node which are visible (i.e. just
- // test their mark flag)
- void render_node_faces(__memBase, int node, int side)
- {
- int i, n, f;
-
- n = bspMem->dnodes[node].numfaces;
- f = bspMem->dnodes[node].firstface;
-
- for (i = 0; i < n; ++i) {
- if (bspMem->dfaces[f].side == side)
- if (is_marked_face(f))
- draw_face(bspMem, f);
- unmark_face(f);
- ++f;
- }
- }
-
- void render_world(__memBase)
- {
- compute_view_frustrum();
- update_water();
-
- //for(model = 0; model < bspMem->nummodels; model++) {
- visit_visible_leaves(bspMem);
- bsp_find_visible_nodes(bspMem, (int)bspMem->dmodels[model].headnode[0]);
- bsp_explore_node(bspMem, (int)bspMem->dmodels[model].headnode[0]);
- bsp_render_node(bspMem, (int)bspMem->dmodels[model].headnode[0]);
- //}
- }
-